<!--**
 * forked from：https://github.com/F-loat/mpvue-wxParse
 *
 * github地址: https://github.com/dcloudio/uParse
 *
 * uni-app框架下 富文本解析
 * 全局引入css文件，@import '/.../wxParse.css';
 * 
 */-->

<template>
  <!--基础元素-->
  <div class="wxParse" :class="className" :style="'user-select:' + userSelect">
    <block v-for="(node, index) of nodes" :key="index">
      <wxParseTemplate :node="node" v-if="!loading"></wxParseTemplate>
    </block>
  </div>
</template>

<script>
  import HtmlToJson from './libs/html2json';
  import wxParseTemplate from './components/wxParseTemplate0';
  import useUpload from '@/hooks/core/useUpload';
  export default {
    name: 'wxParse',
    emits: ['navigate', 'preview'],
    props: {
      userSelect: {
        type: String,
        default: 'text', //none |text| all | element
      },
      imgOptions: {
        type: [Object, Boolean],
        default: function () {
          return {
            loop: false,
            indicator: 'number',
            longPressActions: false,
          };
        },
      },
      loading: {
        type: Boolean,
        default: false,
      },
      className: {
        type: String,
        default: '',
      },
      content: {
        type: String,
        default: '',
      },
      noData: {
        type: String,
        default: '<text></text>',
      },
      startHandler: {
        type: Function,
        default() {
          return (node) => {
            node.attr.class = null;
            node.attr.style = null;
          };
        },
      },
      endHandler: {
        type: Function,
        default: null,
      },
      charsHandler: {
        type: Function,
        default: null,
      },
      imageProp: {
        type: Object,
        default() {
          return {
            mode: 'aspectFit',
            padding: 0,
            lazyLoad: false,
            domain: '',
          };
        },
      },
    },
    components: {
      wxParseTemplate,
    },
    data() {
      return {
        nodes: {},
        imageUrls: [],
        wxParseWidth: {
          value: 0,
        },
      };
    },
    computed: {},
    mounted() {
      this.setHtml();
    },
    methods: {
      setHtml() {
        this.getWidth().then((data) => {
          this.wxParseWidth.value = data;
        });
        let { content, noData, imageProp, startHandler, endHandler, charsHandler } = this;
        let parseData = content || noData;
        let customHandler = {
          start: startHandler,
          end: endHandler,
          chars: charsHandler,
        };
        let results = HtmlToJson(parseData, customHandler, imageProp, this);

        this.imageUrls = results.imageUrls;
        this.nodes = [];

        setTimeout(() => {
          this.nodes = results.nodes;

          // 由于后管富文本编辑器,上传视频必须加入换行符才可以删除视频,所以在此处删除视频前的换行符,避免影响样式
          this.nodes.forEach((v) => {
            if (v.tag === 'p' && v.nodes.length) {
              v.nodes.forEach((node, idx) => {
                if (node.tag === 'video' && idx > 0 && v.nodes[idx - 1].tag === 'br') {
                  v.nodes.splice(idx - 1, 1);
                }
              });
            }
          });
        }, 20);
      },
      getWidth() {
        return new Promise((res, rej) => {
          // #ifndef MP-ALIPAY || MP-BAIDU
          uni
            .createSelectorQuery()
            .in(this)
            .select('.wxParse')
            .fields(
              {
                size: true,
                scrollOffset: true,
              },
              (data) => {
                res(data.width);
              },
            )
            .exec();
          // #endif
          // #ifdef MP-BAIDU
          return new Promise((res, rej) => {
            swan
              .createSelectorQuery()
              .select('.wxParse')
              .boundingClientRect(function (rect) {
                res(rect.width);
              })
              .exec();
          });
          // #endif
          // #ifdef MP-ALIPAY
          my.createSelectorQuery()
            .select('.wxParse')
            .boundingClientRect()
            .exec((ret) => {
              res(ret[0].width);
            });
          // #endif
        });
      },
      navigate(href, $event, attr) {
        this.$emit('navigate', href, $event);
      },
      openDocumentAttachment(filePath, fileType) {
        wx.downloadFile({
          url: filePath,
          success: function (res) {
            const tempFilePath = res.tempFilePath;
            wx.openDocument({
              filePath: tempFilePath,
              fileType,
              success: function (res) {
                console.log('打开文档成功', res);
              },
              fail: function (err) {
                uni.showToast({
                  title: '打开文档失败',
                  icon: 'none',
                });
              },
            });
          },
          fail: function (err) {
            uni.showToast({
              title: '下载文件失败',
              icon: 'none',
            });
          },
        });
      },
      preview(src, $event) {
        if (!this.imageUrls.length || typeof this.imgOptions === 'boolean') {
        } else {
          uni.previewImage({
            current: src,
            urls: this.imageUrls,
            loop: this.imgOptions.loop,
            indicator: this.imgOptions.indicator,
            longPressActions: this.imgOptions.longPressActions,
          });
        }
        this.$emit('preview', src, $event);
      },
      removeImageUrl(src) {
        const { imageUrls } = this;
        imageUrls.splice(imageUrls.indexOf(src), 1);
      },
    },
    // 父组件中提供
    provide() {
      return {
        parseWidth: this.wxParseWidth,
        parseSelect: this.userSelect,
        // 提示：provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而，如果你传入了一个可监听的对象，那么其对象的属性还是可响应的。
      };
    },
    watch: {
      content() {
        this.setHtml();
      },
    },
  };
</script>
